
#include "featuredata.h"


Feature::Feature()
{
	m_gameNum = -1;
	m_level = STARTINGLEVEL;
}


Feature::~Feature()
{
    while ( m_array.size() > 0 )
    {
		FeatureList *fList = m_array.back();
		FeatureArray* fArray = &fList->array;

		while ( fArray->size() > 0 )
		{
			FeatureData *fData = fArray->back();
			delete fData;
			fArray->pop_back();
		}
        delete fList;
        m_array.pop_back();
    }
}


void
Feature::setGameNum(int64 gameNum)
{
	if (gameNum != m_gameNum)
	{
		clearAll();
	}
	m_gameNum = gameNum;
}

int64
Feature::getGameNum()
{
	return m_gameNum;
}

void
Feature::setLevel (int32 level)
{
	m_level = level;
}

int32
Feature::getLevel ()
{
	return m_level;
}


void
Feature::update(uint8 id, int32 data, bool8 serverOnly)
{
	updateLevel (m_level, id, data, serverOnly);
}

void
Feature::updateLevel(uint8 level, uint8 id, int32 data, bool8 serverOnly)
{
	FeatureArray* fArray = getFeatureArray(level);
    bool8 found = false;

    for ( size_t i = 0; i < fArray->size(); i++ )
    {
	    FeatureData *fData;
        fData = (*fArray)[i];

        if ( fData->id == id )
        {
            fData->data = data;
            found = true;
            break;
        }
	}
    if ( !found )
    {
		FeatureData* fData = new FeatureData;
		fData->id = id;
		fData->data = data;
		fData->serverOnly = serverOnly;
		fArray->push_back(fData);
    }
}


int32
Feature::getData(uint8 id)
{
	return getDataLevel(m_level, id);
}

int32
Feature::getDataLevel(uint8 level, uint8 id)
{
	FeatureArray* fArray = getFeatureArray(level);
    int32 data = 0; // Default

    for ( size_t i = 0; i < fArray->size(); i++ )
    {
	    FeatureData *fData;
        fData = (*fArray)[i];

        if ( fData->id == id )
        {
            data = fData->data;
            break;
        }
	}

    return data;
}


bool8
Feature::isServerOnly(uint8 id)
{
	return isServerOnlyLevel(m_level, id);
}

bool8
Feature::isServerOnlyLevel(uint8 level, uint8 id)
{
	FeatureArray* fArray = getFeatureArray(level);
    bool8 serverOnly = true; // Assume restricted access

    for ( size_t i = 0; i < fArray->size(); i++ )
    {
	    FeatureData *fData;
        fData = (*fArray)[i];

        if ( fData->id == id )
        {
            serverOnly = fData->serverOnly;
            break;
        }
	}
    return serverOnly;
}

int32
Feature::getDataCount()
{
	return getFeatureArray(m_level)->size();
}

int32
Feature::getDataCountLevel(uint8 level)
{
	return getFeatureArray(level)->size();
}

int32
Feature::getAllDataCount()
{
	FeatureList* fList;
	int32 count = 0;

	for (size_t i = 0; i < m_array.size(); ++i)
	{
		fList = m_array[i];
		count += fList->array.size();
	}
	return count;
}


int32
Feature::getDataAt(int32 index)
{
	return getDataAtLevel(m_level, index);
}

int32
Feature::getDataAtLevel(uint8 level, int32 index)
{
	FeatureArray* fArray = getFeatureArray(level);
    int32 data = 0; // Default

    if ( index < (int32)fArray->size() )
    {
        FeatureData *fData = (*fArray)[index];
        data = fData->data;
    }
    else
    {
        /**
         * Out of bounds index.
         */
        ASSERT(1);
    }

    return data;
}

int32
Feature::getIdAt(int32 index)
{
	return getIdAtLevel(m_level, index);
}

int32
Feature::getIdAtLevel(uint8 level, int32 index)
{
	FeatureArray* fArray = getFeatureArray(level);
    int id = -1; // implies no data
    if ( index < (int32)fArray->size() )
    {
        FeatureData *fData = (*fArray)[index];
        id = fData->id;
    }
    else
    {
        /**
         * Out of bounds index.
         */
        ASSERT(1);
    }

    return id;
}

bool8
Feature::isServerOnlyAt(int32 index)
{
	return isServerOnlyAtLevel(m_level, index);
}

bool8
Feature::isServerOnlyAtLevel(uint8 level, int32 index)
{
	FeatureArray* fArray = getFeatureArray(level);
    bool8 serverOnly = true; // assume restriction
    if ( index < (int32)fArray->size() )
    {
        FeatureData *fData = (*fArray)[index];
        serverOnly = fData->serverOnly;
    }
    else
    {
        /**
         * Out of bounds index.
         */
        ASSERT(1);
    }
    return serverOnly;
}


int32 
Feature::getLevelCount()
{
	return m_array.size();
}

uint8
Feature::getLevelAt(int32 index)
{
	uint8 level = 0;

    if ( index < (int32)m_array.size() )
    {
		FeatureList* fList = m_array[index];
		level = fList->level;
    }
    else
    {
        /**
         * Out of bounds index.
         */
        ASSERT(1);
    }
    return level;
}




uint8
Feature::getClientOnlyDataSize()
{
	return getClientOnlyDataSizeLevel(m_level);
}

uint8
Feature::getClientOnlyDataSizeLevel(uint8 level)
{
	FeatureArray* fArray = getFeatureArray(level);

    uint8 datasize = 0;
    uint8 arraysize = fArray->size();
    uint8 serveronlycount = 0;

    for ( int i = 0; i < arraysize; i++ )
    {
        if ( (*fArray)[i]->serverOnly )
        {
            ++serveronlycount;
        }
    }

    datasize = arraysize - serveronlycount;

    return datasize;

}

void
Feature::clearAll ()
{
    while ( m_array.size() > 0 )
    {
		FeatureList *fList = m_array.back();
		FeatureArray* fArray = &fList->array;

		while ( fArray->size() > 0 )
		{
			FeatureData *fData = fArray->back();
			delete fData;
			fArray->pop_back();
		}
        delete fList;
        m_array.pop_back();
    }
}

//------------------Private methods -------------------

// Adds the data to the current level.
void
Feature::add(uint8 id, int32 data, bool8 serverOnly)
{
	addLevel (m_level, id, data, serverOnly);
}

// Adds the data to the specified level.
void
Feature::addLevel(uint32 level, uint8 id, int32 data, bool8 serverOnly)
{
	FeatureArray* fArray = getFeatureArray(level);

	if (fArray == NULL)
	{
		FeatureList* fList = new struct FeatureList;
		fList->level = level;
//		fList->array = new FeatureArray();
		m_array.push_back(fList);
		fArray = &fList->array;
	}

    FeatureData *fData = new FeatureData();

    fData->data = data;
    fData->id = id;
    fData->serverOnly = serverOnly;

    fArray->push_back(fData);
}

FeatureArray*
Feature::getFeatureArray(uint8 level)
{
	FeatureArrayVec::iterator it;
	FeatureArray* fArray = NULL;

	// Look for the level in the current vec
	for (it = m_array.begin(); it != m_array.end(); ++it)
	{
		FeatureList* fList = *it;
		if (fList->level == level)
		{
			fArray = &fList->array;
		}
	}

	// If the level is not found then create a new one and
	// add it to the list.
	if (fArray == NULL)
	{
		FeatureList* fList = new FeatureList;
		fList->level = level;
//		fList->array = new FeatureArray();
		m_array.push_back(fList);
		fArray = &fList->array;
	}
	return fArray;

}
